package com.leps.nq.login;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import com.leps.nq.common.SysConsts;
import com.leps.nq.common.async.AsyncFactory;
import com.leps.nq.common.async.AsyncManager;
import com.leps.nq.common.exception.BadCredentialsException;
import com.leps.nq.common.exception.UserStatusDisabledException;
import com.leps.nq.common.vo.R;
import com.leps.nq.common.vo.RBuilder;
import com.leps.nq.sys.entity.SysRole;
import com.leps.nq.sys.entity.SysUser;
import com.leps.nq.sys.service.ISysMenuService;
import com.leps.nq.sys.service.ISysUserService;
import com.leps.nq.sys.vo.MenuInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Objects;

@RestController
@Api(tags = "登录与注销")
public class LoginController {
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysMenuService menuService;

    @PostMapping("/login")
    @ApiOperation("用户登录")
    public R<LoginSuccessModel> login(@RequestBody LoginModel loginModel) {
        final String userName = loginModel.getUserName();
        final String password = loginModel.getPassword();
        // check credentials
        SysUser selectUser = this.userService.selectUserByUserName(userName);
        if (Objects.isNull(selectUser)) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, SysConsts.LOGIN_FAIL, "帐号错误"));
            throw new BadCredentialsException();
        }
        boolean pwmatched = BCrypt.checkpw(password, selectUser.getPassword());
        if (!pwmatched) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, SysConsts.LOGIN_FAIL, "密码错误"));
            throw new BadCredentialsException();
        }
        if ("1".equals(selectUser.getStatus())) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, SysConsts.LOGIN_FAIL, "帐号被锁定"));
            throw new UserStatusDisabledException();
        }
        // login success
        StpUtil.login(selectUser.getUserId());
        SaSession session = StpUtil.getSession();
        session.set("userName", selectUser.getUserName());
        String tokenName = StpUtil.getTokenInfo().getTokenName();
        String tokenValue = StpUtil.getTokenInfo().getTokenValue();
        // 查询用户拥有的角色
        List<SysRole> roles = this.userService.selectRolesByUserId(selectUser.getUserId());
        // 查询用户拥有的菜单
        List<MenuInfoVo> menus = userService.selectMenusByUserId(selectUser.getUserId());
        // 查询用户拥有的权限码
        List<String> perms = userService.selectPermsByUserId(selectUser.getUserId());
        // 返回
        LoginSuccessModel loginSuccessModel = new LoginSuccessModel(tokenName, tokenValue, roles, menus, perms);
        // 更新登录时间，IP等
        this.userService.updateLoginInfo();
        // 异步记录登录日志
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, SysConsts.LOGIN_SUCCESS, "登录成功"));
        // 返回结果
        return RBuilder.ok(loginSuccessModel);
    }

    @DeleteMapping("/logout")
    @ApiOperation("用户注销")
    public void logout() {
        StpUtil.logout();
    }
}
